const nodeDir = require("node-dir");
const fs = require("fs-extra");
const path = require("path");

import antlr4 from 'antlr4';
import cLexer from './parser/CLexer';
import CListener from './parser/CListener';
import cParser from './parser/cParser';

const KIND_VARTYPE = "vartype";
const KIND_FUNCTYPE = "functype"
const KIND_INTERFACE = "interface";
const KIND_TYPEDEF = "typedef";

const TYPE_BASE = "base";
const TYPE_ENUM = "enum";
const TYPE_STRUCT = "struct";
const TYPE_UNION = "union";

const STATE_TOP_DECL = "STATE_TOP_DECL"
const STATE_INTERFACE_DECL = "STATE_INTERFACE_DECL";
const STATE_FIELD_VAR_DECL = "STATE_FIELD_VAR_DECL";
const STATE_FIELD_FUN_DECL = "STATE_FIELD_FUN_DECL";
const STATE_FIELD_FUN_PARAM_DECL = "STATE_FIELD_FUN_PARAM_DECL";

const STATE_FUN_DECL = "STATE_FUN_DECL";
const STATE_FUNC_RETURN_TYPE_DECL = "STATE_FUNC_RETURN_TYPE_DECL";
const STATE_FUNC_NAME_DECL = "STATE_FUNC_NAME_DECL";
const STATE_FUN_PARAM_DECL = "STATE_FUN_PARAM_DECL";

const STATE_VAR_TYPE_DECL = "STATE_VAR_TYPE_DECL";

let decls = [];
// 当前类型
let defaultObj = () => {
	return {
		kind:"", //KIND_xx
		type:"", //enum|struct|union
		name:"",
		/*
			{
				type:"",
				key:"",
				value:""
			}
		*/ 
		fields:[]
	}
} ;

let currentState = STATE_TOP_DECL;
let currentObj = defaultObj();
// 字段的多类型说明
let currentType = []


class myListener extends CListener{
    // Enter a parse tree produced by CParser#compilationUnit.
	enterCompilationUnit(ctx) {
        // log("enterCompilationUnit",ctx.getText());
	}

	// Exit a parse tree produced by CParser#compilationUnit.
	exitCompilationUnit(ctx) {
	}


	// Enter a parse tree produced by CParser#translationUnit.
	enterTranslationUnit(ctx) {
        // log("enterTranslationUnit",ctx.getText());
	}

	// Exit a parse tree produced by CParser#translationUnit.
	exitTranslationUnit(ctx) {
        // ljson(decls);
		let outFile = path.join(
			__dirname,
			"/out/json/ffmpeg.json"
		);
		writeToFile(outFile,decls)
	}


	// Enter a parse tree produced by CParser#externalDeclaration.
	enterExternalDeclaration(ctx) {
        // 顶级声明
        // log("enterExternalDeclaration",ctx.getText());
	}

	// Exit a parse tree produced by CParser#externalDeclaration.
	exitExternalDeclaration(ctx) {
        // ljson(decls);
		
	}


	// Enter a parse tree produced by CParser#functionDefinition.
	enterFunctionDefinition(ctx) {
        // // 顶级声明
        // log("enterFunctionDefinition",ctx.getText());
	}

	// Exit a parse tree produced by CParser#functionDefinition.
	exitFunctionDefinition(ctx) {
	}


	// Enter a parse tree produced by CParser#declarationList.
	enterDeclarationList(ctx) {
        
	}

	// Exit a parse tree produced by CParser#declarationList.
	exitDeclarationList(ctx) {
        
	}


	// Enter a parse tree produced by CParser#declaration.
	enterDeclaration(ctx) {
        // // 顶级声明
        // this.logChild(ctx,"enterDeclaration");
		currentObj.kind = "";
		let tempText = this.text(ctx);
		if(tempText.includes(TYPE_STRUCT) 
			|| tempText.includes(TYPE_UNION) 
			||  tempText.includes(TYPE_ENUM) ){
			currentObj.kind = tempText.includes(KIND_TYPEDEF) 
				? KIND_TYPEDEF
				: KIND_INTERFACE;
			
			currentState = STATE_INTERFACE_DECL;

		}else if(tempText.includes("extern")){
			currentObj.kind = KIND_VARTYPE;

			currentState = STATE_VAR_TYPE_DECL;
		}else{
			currentObj.kind = KIND_FUNCTYPE;

			currentState = STATE_FUN_DECL;
		}

	}

	// Exit a parse tree produced by CParser#declaration.
	exitDeclaration(ctx) {
		currentState = STATE_TOP_DECL;
		currentObj = defaultObj();
	}


	// Enter a parse tree produced by CParser#declarationSpecifiers.
	enterDeclarationSpecifiers(ctx) {
        //  // 顶级声明
        //  log("enterDeclarationSpecifiers",ctx.getText());
	}

	// Exit a parse tree produced by CParser#declarationSpecifiers.
	exitDeclarationSpecifiers(ctx) {
	}


	// Enter a parse tree produced by CParser#initDeclaratorList.
	enterInitDeclaratorList(ctx) {
		if(currentState == STATE_FUN_DECL){
			//切换到参数
			let tempText = this.text(ctx);
			if(tempText.includes("(")){
				if( tempText[0] == "("){
					currentState = STATE_FUN_PARAM_DECL;
				}else{
					currentObj.name = tempText.split("(")[0];
				}
			}else if(tempText[tempText.length - 1] == ']'){
				// array
			}
		}
		// this.logChild(ctx,"initDeclaratorList");
	}
	// Exit a parse tree produced by CParser#initDeclaratorList.
	exitInitDeclaratorList(ctx) {
		// currentState = STATE_FUN_DECL;
		// log("exitInitDeclaratorList");
		// ljson(currentObj);
	}


	// Enter a parse tree produced by CParser#initDeclarator.
	enterInitDeclarator(ctx) {
		// this.logChild(ctx,"enterInitDeclarator");
	}

	// Exit a parse tree produced by CParser#initDeclarator.
	exitInitDeclarator(ctx) {
	}


	// Enter a parse tree produced by CParser#staticAssertDeclaration.
	enterStaticAssertDeclaration(ctx) {
	}

	// Exit a parse tree produced by CParser#staticAssertDeclaration.
	exitStaticAssertDeclaration(ctx) {
	}


	// Enter a parse tree produced by CParser#declarationSpecifier.
	enterDeclarationSpecifier(ctx) {
        // 顶级声明
        // log("enterDeclarationSpecifier",ctx.getText());
	}

	// Exit a parse tree produced by CParser#declarationSpecifier.
	exitDeclarationSpecifier(ctx) {
	}


	// Enter a parse tree produced by CParser#storageClassSpecifier.
	enterStorageClassSpecifier(ctx) {
        // 顶级声明
        // log("enterStorageClassSpecifier",ctx.getText());
	}

	// Exit a parse tree produced by CParser#storageClassSpecifier.
	exitStorageClassSpecifier(ctx) {
	}


	// Enter a parse tree produced by CParser#typeSpecifier.
	enterTypeSpecifier(ctx) {
        // 类型信息
		if(currentState == STATE_FUN_DECL 
			&& !currentObj.type){
			currentObj.type = this.text(ctx);
		}else if(currentState == STATE_VAR_TYPE_DECL ){
			log("enterTypeSpecifier",currentState);
			
			this.logChild(ctx,"enterTypeSpecifier");

		}
	}

	// Exit a parse tree produced by CParser#typeSpecifier.
	exitTypeSpecifier(ctx) {
	}


	// Enter a parse tree produced by CParser#atomicTypeSpecifier.
	enterAtomicTypeSpecifier(ctx) {
        // 类型
        // log("enterAtomicTypeSpecifier",ctx.getText());
	}

	// Exit a parse tree produced by CParser#atomicTypeSpecifier.
	exitAtomicTypeSpecifier(ctx) {
	}


	// Enter a parse tree produced by CParser#typeName.
	enterTypeName(ctx) {
		// this.logChild(ctx.getText(),"enterAtomicTypeSpecifier");
	}

	// Exit a parse tree produced by CParser#typeName.
	exitTypeName(ctx) {
	}


	// Enter a parse tree produced by CParser#structOrUnionSpecifier.
	enterStructOrUnionSpecifier(ctx) {
        // 结构体
        // log("enterStructOrUnionSpecifier",ctx.getText());
        // log("name",ctx.getChild(1).getText());
        // this.logChild(ctx,"enterStructOrUnionSpecifier");
        currentObj.type =  ctx.getChild(0).getText();
		currentObj.name =  this.nameFix(ctx.getChild(1).getText());
    }

	// Exit a parse tree produced by CParser#structOrUnionSpecifier.
	exitStructOrUnionSpecifier(ctx) {
		decls.push(currentObj);
	}


	// Enter a parse tree produced by CParser#structOrUnion.
	enterStructOrUnion(ctx) {
        // struct|union关键词
        // log("enterStructOrUnion",ctx.getText());
	}

	// Exit a parse tree produced by CParser#structOrUnion.
	exitStructOrUnion(ctx) {
	}


	// Enter a parse tree produced by CParser#structDeclarationList.
	enterStructDeclarationList(ctx) {
        // 结构体字段列表
        // log("enterStructDeclarationList",ctx.getText());
        
    }

	// Exit a parse tree produced by CParser#structDeclarationList.
	exitStructDeclarationList(ctx) {
	}


	// Enter a parse tree produced by CParser#structDeclaration.
	enterStructDeclaration(ctx) {
        // 结构体中单个字段 类型+字段名+;
        // log("enterStructDeclaration",ctx.getText());
        // this.logChild(ctx,"enterStructDeclaration");
	}

	// Exit a parse tree produced by CParser#structDeclaration.
	exitStructDeclaration(ctx) {
	}


	// Enter a parse tree produced by CParser#specifierQualifierList.
	enterSpecifierQualifierList(ctx) {
        // 结构体中单个字段+字段名称
        // log("enterSpecifierQualifierList",this.text(ctx));
		// this.logChild(ctx,"enterSpecifierQualifierList");
        // log("name",currentObj);
		if(ctx.getChildCount() == 2){
			let tempText = this.text(ctx.getChild(0))
			if(tempText.includes("enum")){
				// currentType.push("enum");
				currentType.push(tempText.replace("enum",""));
			}else{
				currentType.push(this.text(ctx.getChild(0)));
			}
		}

        // this.logChild(ctx,"enterSpecifierQualifierList");
    }

	// Exit a parse tree produced by CParser#specifierQualifierList.
	exitSpecifierQualifierList(ctx) {
		// 字段
		if(ctx.getChildCount() == 1){ //生成类型
			currentObj.fields.push({
				type:currentType.join(" "),
				key:ctx.getChild(0).getText(),
				value:""
			})
			currentType = [];
		}
	}


	// Enter a parse tree produced by CParser#structDeclaratorList.
	enterStructDeclaratorList(ctx) {
        // 复杂字段结构
        // log("enterStructDeclaratorList",ctx.getText());
		// this.logChild(ctx,"enterStructDeclaratorList");
	}

	// Exit a parse tree produced by CParser#structDeclaratorList.
	exitStructDeclaratorList(ctx) {
	}


	// Enter a parse tree produced by CParser#structDeclarator.
	enterStructDeclarator(ctx) {
		// 复杂声明
        // log("enterStructDeclarator",ctx.getText());
		// this.logChild(ctx,"enterStructDeclarator");
	}

	// Exit a parse tree produced by CParser#structDeclarator.
	exitStructDeclarator(ctx) {
	}


	// Enter a parse tree produced by CParser#enumSpecifier.
	enterEnumSpecifier(ctx) {
        // enumXX 枚举与名称
        // log("enterEnumSpecifier",ctx.getText(),ctx.getChildCount());
        // ctx.children.forEach(c => {
        //     log("c",c.getText());
        // })
		if(ctx.getChildCount() > 2){
			currentObj.type = "enum";
			currentObj.name = this.nameFix(ctx.getChild(1).getText());
		}
	}

	// Exit a parse tree produced by CParser#enumSpecifier.
	exitEnumSpecifier(ctx) {
		if(ctx.getChildCount() > 2 
			&& currentObj.fields.length > 0){ //enum的声明与引用
			decls.push(currentObj);
		}
	}


	// Enter a parse tree produced by CParser#enumeratorList.
	enterEnumeratorList(ctx) {
        // 枚举字段列表
	}

	// Exit a parse tree produced by CParser#enumeratorList.
	exitEnumeratorList(ctx) {
	}


	// Enter a parse tree produced by CParser#enumerator.
	enterEnumerator(ctx) {
        // 单个枚举字段
        currentObj.fields.push({
			type:"int",
            key:ctx.getChild(0).getText(),
            value:ctx.getChildCount() == 3
                ? ctx.getChild(2).getText()
                : ""
        });
        
	}

	// Exit a parse tree produced by CParser#enumerator.
	exitEnumerator(ctx) {
	}


	// Enter a parse tree produced by CParser#enumerationConstant.
	enterEnumerationConstant(ctx) {
        // log("enterEnumerationConstant",ctx.getText());
	}

	// Exit a parse tree produced by CParser#enumerationConstant.
	exitEnumerationConstant(ctx) {
	}


	// Enter a parse tree produced by CParser#typedefName.
	enterTypedefName(ctx) {
        // typedefName 名称字段
		if(currentState == STATE_FUN_DECL 
			&& currentObj.kind == KIND_FUNCTYPE){
			// this.logChild(ctx,"enterTypedefName");
			currentObj.name = ctx.getText();
		}else if(currentState == STATE_VAR_TYPE_DECL ){
			this.logChild(ctx,"enterTypedefName");
		}
	}

	// Exit a parse tree produced by CParser#typedefName.
	exitTypedefName(ctx) {
        
	}



	// Enter a parse tree produced by CParser#constantExpression.
	enterConstantExpression(ctx) {
        // log("enterConstantExpression",ctx.getText());
	}

	// Exit a parse tree produced by CParser#constantExpression.
	exitConstantExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#pointer.
	enterPointer(ctx) {
        // 指针的*
        // log("enterPointer",ctx.getText());
	}

	// Exit a parse tree produced by CParser#pointer.
	exitPointer(ctx) {
	}


	// Enter a parse tree produced by CParser#typeQualifier.
	enterTypeQualifier(ctx) {
        // log("enterTypeQualifier",ctx.getText());
	}

	// Exit a parse tree produced by CParser#typeQualifier.
	exitTypeQualifier(ctx) {
	}


	// Enter a parse tree produced by CParser#functionSpecifier.
	enterFunctionSpecifier(ctx) {
        // log("enterFunctionSpecifier",ctx.getText());
	}

	// Exit a parse tree produced by CParser#functionSpecifier.
	exitFunctionSpecifier(ctx) {
	}


	// Enter a parse tree produced by CParser#gccAttributeSpecifier.
	enterGccAttributeSpecifier(ctx) {
        
	}

	// Exit a parse tree produced by CParser#gccAttributeSpecifier.
	exitGccAttributeSpecifier(ctx) {
	}


	// Enter a parse tree produced by CParser#gccAttributeList.
	enterGccAttributeList(ctx) {
	}

	// Exit a parse tree produced by CParser#gccAttributeList.
	exitGccAttributeList(ctx) {
	}


	// Enter a parse tree produced by CParser#gccAttribute.
	enterGccAttribute(ctx) {
	}

	// Exit a parse tree produced by CParser#gccAttribute.
	exitGccAttribute(ctx) {
	}


	// Enter a parse tree produced by CParser#alignmentSpecifier.
	enterAlignmentSpecifier(ctx) {
	}

	// Exit a parse tree produced by CParser#alignmentSpecifier.
	exitAlignmentSpecifier(ctx) {
	}


	// Enter a parse tree produced by CParser#declarator.
	enterDeclarator(ctx) {
        // this.logChild(ctx,"enterDeclarator");
	}

	// Exit a parse tree produced by CParser#declarator.
	exitDeclarator(ctx) {
	}


	// Enter a parse tree produced by CParser#directDeclarator.
	enterDirectDeclarator(ctx) {
        // this.logChild(ctx,"enterDirectDeclarator");
		let childNum = ctx.getChildCount();

		if(currentState == STATE_FUN_PARAM_DECL && childNum >= 2){
			let types = [];
			let key = "";

			for(let i = 0; i< childNum; i++){

				// log("c",this.text(ctx.getChild(i)));
				if(i == childNum - 2){
					key = this.text(ctx.getChild(i));
				}else{
					if(i < childNum - 2 &&  ctx.getChild(i).getText()){
						types.push(this.text(ctx.getChild(i)));
					}
				}
			}
			currentObj.fields.push({
				type:types.join(" ").trim(),
				key:key,
				value:""
			})
		}
		// this.logChild(ctx,"enterDirectDeclarator");
	}

	// Exit a parse tree produced by CParser#directDeclarator.
	exitDirectDeclarator(ctx) {
	}


	// Enter a parse tree produced by CParser#typeQualifierList.
	enterTypeQualifierList(ctx) {
        // log("enterTypeQualifierList",ctx.getText());
	}

	// Exit a parse tree produced by CParser#typeQualifierList.
	exitTypeQualifierList(ctx) {
	}


	// Enter a parse tree produced by CParser#assignmentExpression.
	enterAssignmentExpression(ctx) {
        // log("enterAssignmentExpression",ctx.getText());
	}

	// Exit a parse tree produced by CParser#assignmentExpression.
	exitAssignmentExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#conditionalExpression.
	enterConditionalExpression(ctx) {
        // log("enterConditionalExpression",ctx.getText());
	}

	// Exit a parse tree produced by CParser#conditionalExpression.
	exitConditionalExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#logicalOrExpression.
	enterLogicalOrExpression(ctx) {
	}

	// Exit a parse tree produced by CParser#logicalOrExpression.
	exitLogicalOrExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#logicalAndExpression.
	enterLogicalAndExpression(ctx) {
	}

	// Exit a parse tree produced by CParser#logicalAndExpression.
	exitLogicalAndExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#inclusiveOrExpression.
	enterInclusiveOrExpression(ctx) {
	}

	// Exit a parse tree produced by CParser#inclusiveOrExpression.
	exitInclusiveOrExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#exclusiveOrExpression.
	enterExclusiveOrExpression(ctx) {
	}

	// Exit a parse tree produced by CParser#exclusiveOrExpression.
	exitExclusiveOrExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#andExpression.
	enterAndExpression(ctx) {
	}

	// Exit a parse tree produced by CParser#andExpression.
	exitAndExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#equalityExpression.
	enterEqualityExpression(ctx) {
	}

	// Exit a parse tree produced by CParser#equalityExpression.
	exitEqualityExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#relationalExpression.
	enterRelationalExpression(ctx) {
	}

	// Exit a parse tree produced by CParser#relationalExpression.
	exitRelationalExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#shiftExpression.
	enterShiftExpression(ctx) {
	}

	// Exit a parse tree produced by CParser#shiftExpression.
	exitShiftExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#additiveExpression.
	enterAdditiveExpression(ctx) {
	}

	// Exit a parse tree produced by CParser#additiveExpression.
	exitAdditiveExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#multiplicativeExpression.
	enterMultiplicativeExpression(ctx) {
	}

	// Exit a parse tree produced by CParser#multiplicativeExpression.
	exitMultiplicativeExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#castExpression.
	enterCastExpression(ctx) {
	}

	// Exit a parse tree produced by CParser#castExpression.
	exitCastExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#unaryExpression.
	enterUnaryExpression(ctx) {
	}

	// Exit a parse tree produced by CParser#unaryExpression.
	exitUnaryExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#postfixExpression.
	enterPostfixExpression(ctx) {
	}

	// Exit a parse tree produced by CParser#postfixExpression.
	exitPostfixExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#primaryExpression.
	enterPrimaryExpression(ctx) {
	}

	// Exit a parse tree produced by CParser#primaryExpression.
	exitPrimaryExpression(ctx) {
	}


	// Enter a parse tree produced by CParser#genericSelection.
	enterGenericSelection(ctx) {
	}

	// Exit a parse tree produced by CParser#genericSelection.
	exitGenericSelection(ctx) {
	}


	// Enter a parse tree produced by CParser#genericAssocList.
	enterGenericAssocList(ctx) {
	}

	// Exit a parse tree produced by CParser#genericAssocList.
	exitGenericAssocList(ctx) {
	}


	// Enter a parse tree produced by CParser#genericAssociation.
	enterGenericAssociation(ctx) {
	}

	// Exit a parse tree produced by CParser#genericAssociation.
	exitGenericAssociation(ctx) {
	}


	// Enter a parse tree produced by CParser#argumentExpressionList.
	enterArgumentExpressionList(ctx) {
	}

	// Exit a parse tree produced by CParser#argumentExpressionList.
	exitArgumentExpressionList(ctx) {
	}


	// Enter a parse tree produced by CParser#unaryOperator.
	enterUnaryOperator(ctx) {
	}

	// Exit a parse tree produced by CParser#unaryOperator.
	exitUnaryOperator(ctx) {
	}


	// Enter a parse tree produced by CParser#assignmentOperator.
	enterAssignmentOperator(ctx) {
	}

	// Exit a parse tree produced by CParser#assignmentOperator.
	exitAssignmentOperator(ctx) {
	}


	// Enter a parse tree produced by CParser#parameterTypeList.
	enterParameterTypeList(ctx) {
        // 参数类型
		// log("param")
		currentState = STATE_FUN_PARAM_DECL;
        // this.logChild(ctx,"enterParameterTypeList");
	}

	// Exit a parse tree produced by CParser#parameterTypeList.
	exitParameterTypeList(ctx) {
		currentState = STATE_FUN_DECL;
		// this.logChild(ctx,"exitParameterTypeList");
		// ljson(currentObj);
		decls.push(currentObj);
	}


	// Enter a parse tree produced by CParser#parameterList.
	enterParameterList(ctx) {
        // 
		// this.logChild(ctx,"enterParameterList");
	}

	// Exit a parse tree produced by CParser#parameterList.
	exitParameterList(ctx) {
		// ljson(currentObj);
	}


	// Enter a parse tree produced by CParser#parameterDeclaration.
	enterParameterDeclaration(ctx) {
        // log("enterParameterDeclaration",ctx.getText());
		// this.logChild(ctx,"enterParameterDeclaration");
		currentObj.fields.push({
			type: this.text(ctx.getChild(0)),
			key:ctx.getChildCount() > 1
				? ctx.getChild(1).getText()
				 : "", //void
			value:""
		});
	}

	// Exit a parse tree produced by CParser#parameterDeclaration.
	exitParameterDeclaration(ctx) {
	}


	// Enter a parse tree produced by CParser#declarationSpecifiers2.
	enterDeclarationSpecifiers2(ctx) {
        // log("enterDeclarationSpecifiers2",ctx.getText());
	}

	// Exit a parse tree produced by CParser#declarationSpecifiers2.
	exitDeclarationSpecifiers2(ctx) {
	}


	// Enter a parse tree produced by CParser#abstractDeclarator.
	enterAbstractDeclarator(ctx) {
        // log("enterAbstractDeclarator",ctx.getText());
	}

	// Exit a parse tree produced by CParser#abstractDeclarator.
	exitAbstractDeclarator(ctx) {
	}


	// Enter a parse tree produced by CParser#directAbstractDeclarator.
	enterDirectAbstractDeclarator(ctx) {
	}

	// Exit a parse tree produced by CParser#directAbstractDeclarator.
	exitDirectAbstractDeclarator(ctx) {
	}


	// Enter a parse tree produced by CParser#gccDeclaratorExtension.
	enterGccDeclaratorExtension(ctx) {
	}

	// Exit a parse tree produced by CParser#gccDeclaratorExtension.
	exitGccDeclaratorExtension(ctx) {
	}

	// Enter a parse tree produced by CParser#identifierList.
	enterIdentifierList(ctx) {
        // log("enterIdentifierList",ctx.getText());
	}

	// Exit a parse tree produced by CParser#identifierList.
	exitIdentifierList(ctx) {
	}


	// Enter a parse tree produced by CParser#initializer.
	enterInitializer(ctx) {
        // log("enterInitializer",ctx.getText());
	}

	// Exit a parse tree produced by CParser#initializer.
	exitInitializer(ctx) {
	}


	// Enter a parse tree produced by CParser#initializerList.
	enterInitializerList(ctx) {
        // log("enterInitializerList",ctx.getText());
	}

	// Exit a parse tree produced by CParser#initializerList.
	exitInitializerList(ctx) {
	}


	// Enter a parse tree produced by CParser#designation.
	enterDesignation(ctx) {
	}

	// Exit a parse tree produced by CParser#designation.
	exitDesignation(ctx) {
	}


	// Enter a parse tree produced by CParser#designatorList.
	enterDesignatorList(ctx) {
	}

	// Exit a parse tree produced by CParser#designatorList.
	exitDesignatorList(ctx) {
	}


	// Enter a parse tree produced by CParser#designator.
	enterDesignator(ctx) {
	}

	// Exit a parse tree produced by CParser#designator.
	exitDesignator(ctx) {
	}


    logChild(ctx,name){
        log(name);
		log("state->"+currentState);
		log(this.text(ctx));
		log("-------child---------|");
        ctx.children.forEach(c => {
            log(this.text(c));
        })
		log("-------child---------|");
    }

	nameFix(text){
		return text == "{"  ? "" : text;
	}

	text(ctx){
		if (ctx.getChildCount() === 0) {
			return "";
		} else {
			return ctx.children.map(function(child) {
				return child.getText();
			}).join(" ").trim();
		}	
	}
}

class parseHeader{
    constructor(){
        
    }

    parseFile(file)
    {
        fs.readFile(file,"utf8",(err,data)=>{
            if(err){
                log("err",err);
            }
            const chars = new antlr4.InputStream(data);
            const lexer = new cLexer(chars);
            const tokens  = new antlr4.CommonTokenStream(lexer);
            const parser = new cParser(tokens);
            parser.buildParseTrees = true;
            const tree = parser.compilationUnit();

            antlr4.tree.ParseTreeWalker.DEFAULT.walk(new myListener(), tree);

            // tree.accept(new myVisitor());

            // log("d",decls);
            // let outFile  =  path.join(__dirname,"/out/"+file.replace(".h",".json"));
            // fs.ensureFile(outFile).then(()=>{
            //     fs.writeJSON(outFile,decls,{spaces:4})
            //     .then(()=>{
            //         log("write ok",outFile);
            //     })
            //     .catch((err)=>{
            //         log("err",err);
            //     });
            // })

            // antlr4.tree
            
        })
    }
}


function genType()
{
    let tempfile = "./ffmpeg/fftools/ffmpeg.h";
    const parser = new parseHeader();
    parser.parseFile(tempfile);
}
genType();

// 删除不是.h的文件
function delNoHeader(dir)
{
    nodeDir.files(dir,(direrr,files)=>{
        files.forEach(file => {
           if(path.extname(file) != ".h"){
               fs.unlink(file,err => {
                   if(err){
                       log(`remove ${file}`,"error", err);
                   }else{
                       log(`remove ${file}`,"ok");
                   }
               })
           }
        })
    })
}


function t1()
{
    let dirPath = path.join(__dirname,"ffmpeg");
    log(dirPath);
    delNoHeader(dirPath);
}
// t1();

function log(...msg)
{
    console.log(msg);
}

function ljson(msg)
{
    console.log(JSON.stringify(msg,null,4));
}

const writeToFile = function(path, buffer){
    fs.ensureFile(path).then(()=>{
		fs.writeJSON(path,buffer,{spaces:4})
		.then(()=>{
			log("write ok",path);
		})
		.catch((err)=>{
			log("err",err);
		});
	})
}